import os
import shutil
import sys
from pathlib import Path

from PyQt6.QtGui import QIntValidator
from PyQt6.QtWidgets import (
    QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,
    QListWidget, QPushButton, QLabel, QSlider,
    QComboBox, QLineEdit, QListWidgetItem, QCheckBox, QFileDialog, QProgressDialog, QMessageBox
)
from PyQt6.QtCore import Qt, QTimer
import vlc
from sqlalchemy.orm import joinedload

from core.database import SessionLocal
from core.models import Video
from core.operations import get_all_videos, rate_video, search_videos, add_tag_to_video, get_video_by_id, get_all_tags, \
    search_videos_advanced
from qfluentwidgets import (
    FluentWindow, NavigationItemPosition, setTheme, Theme,
    PrimaryPushButton, PushButton, ComboBox, LineEdit, ListWidget,
    Slider, CheckBox, CaptionLabel, StrongBodyLabel, BodyLabel, FluentIcon as FIF
)

class VideoPlayerWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("视频管理系统")
        self.resize(1400, 900)

        # 初始化
        self.init_vlc()
        self.setup_ui()
        self.load_real_data()  # 改为加载真实数据
        self.load_tags()  # 初始化时加载标签

    def init_vlc(self):
        """安全初始化VLC"""
        if sys.platform == "win32":
            os.environ['VLC_PLUGIN_PATH'] = r"C:\Program Files\VideoLAN\VLC\plugins"
            # 添加TS文件解码参数
        vlc_args = [
            "--no-xlib",
            "--avcodec-hw=none",
            "--demux=ts",  # 强制使用TS解复用器
            "--codec=avcodec",
            "--network-caching=2000"  # 增加缓存
        ]
        self.instance = vlc.Instance(vlc_args)
        self.player = self.instance.media_player_new()

    def setup_ui(self):
        """创建完整界面（调整搜索按钮位置）"""
        main_widget = QWidget()
        main_layout = QHBoxLayout(main_widget)

        # 左侧视频列表 (40%)
        left_panel = QVBoxLayout()

        # 搜索输入行
        search_input_layout = QHBoxLayout()
        self.search_input = QLineEdit(placeholderText="输入视频名称...")
        self.search_btn = QPushButton("搜索")
        self.search_btn.clicked.connect(self.on_search)
        search_input_layout.addWidget(self.search_input)
        search_input_layout.addWidget(self.search_btn)
        left_panel.addLayout(search_input_layout)

        # 搜索条件区域
        search_options_layout = QHBoxLayout()

        # 标签搜索
        self.search_tag_combo = QComboBox()
        self.search_tag_combo.addItem("所有标签", None)

        search_options_layout.addWidget(self.search_tag_combo)

        # 评分搜索
        self.search_score_input = QLineEdit()
        self.search_score_input.setPlaceholderText("1-10")
        self.search_score_input.setValidator(QIntValidator(1, 10))
        self.search_score_input.setMaximumWidth(50)
        search_options_layout.addWidget(self.search_score_input)

        # 复选框
        self.untagged_check = QCheckBox("仅未标记")
        self.unrated_check = QCheckBox("仅未评分")
        search_options_layout.addWidget(self.untagged_check)
        search_options_layout.addWidget(self.unrated_check)

        left_panel.addLayout(search_options_layout)

        # 视频列表
        self.video_list = QListWidget()
        self.video_list.setStyleSheet("""
            QListWidget {
                font-size: 12px;
                border: 1px solid #e0e0e0;
                background-color: white;
            }
            QListWidget::item {
                padding: 8px;
                border-bottom: 1px solid #f0f0f0;
                color: black;
            }
            QListWidget::item:hover {
                background-color: #e6f3ff;
            }
            QListWidget::item:selected {
                background-color: #0066CC;
                color: white;
                font-weight: bold;
                border-left: 3px solid #003366;
            }
        """)
        left_panel.addWidget(self.video_list, stretch=1)
        main_layout.addLayout(left_panel, stretch=2)

        # 右侧功能区 (60%)
        right_panel = QVBoxLayout()

        # 视频播放区
        self.video_widget = QWidget()
        self.video_widget.setStyleSheet("background-color: black;")
        self.video_widget.setMinimumSize(800, 500)
        right_panel.addWidget(self.video_widget, stretch=4)

        # 控制栏
        control_layout = QHBoxLayout()
        self.play_btn = QPushButton("播放")
        self.play_btn.clicked.connect(self.toggle_play_pause)
        control_layout.addWidget(self.play_btn)

        self.time_label = QLabel("0:00")
        control_layout.addWidget(self.time_label)

        self.progress_slider = QSlider(Qt.Orientation.Horizontal)
        self.progress_slider.setRange(0, 1000)
        self.progress_slider.sliderPressed.connect(self.on_slider_pressed)
        self.progress_slider.sliderReleased.connect(self.on_slider_released)
        control_layout.addWidget(self.progress_slider, stretch=1)
        right_panel.addLayout(control_layout, stretch=1)

        # 标签和评分编辑区
        edit_panel = QHBoxLayout()

        self.tag_combo = QComboBox()
        edit_panel.addWidget(self.tag_combo, stretch=1)



        edit_panel.addWidget(QLabel("评分:"))

        self.score_input = QLineEdit()
        self.score_input.setValidator(QIntValidator(1, 10))
        self.score_input.setMaximumWidth(50)
        edit_panel.addWidget(self.score_input)

        self.save_btn = QPushButton("保存")
        self.save_btn.clicked.connect(self.on_save)
        edit_panel.addWidget(self.save_btn, stretch=1)
        # 新增导入按钮
        self.import_btn = QPushButton("导入视频")
        self.import_btn.clicked.connect(self.on_import_videos)
        # 在 setup_ui 中添加
        edit_panel.setSpacing(10)  # 按钮间距
        edit_panel.setContentsMargins(0, 5, 0, 5)  # 上下边距


        edit_panel.addWidget(self.import_btn, stretch=1)


        right_panel.addLayout(edit_panel, stretch=1)

        # 操作按钮
        btn_layout = QHBoxLayout()
        self.delete_btn = QPushButton("删除选中")
        self.delete_btn.clicked.connect(self.on_delete)
        btn_layout.addWidget(self.delete_btn)

        # 批量删除按钮
        self.batch_delete_btn = QPushButton("批量删除")

        self.batch_delete_btn.clicked.connect(self.on_batch_delete)
        btn_layout.addWidget(self.batch_delete_btn)

        self.batch_archive_btn = QPushButton("批量归档")

        self.batch_archive_btn.clicked.connect(self.on_batch_archive)
        btn_layout.addWidget(self.batch_archive_btn)

        right_panel.addLayout(btn_layout, stretch=1)
        main_layout.addLayout(right_panel, stretch=8)

        self.setCentralWidget(main_widget)

    def on_batch_archive(self):
        confirm = QMessageBox.question(
            self, "确认归档",
            f"即将归档所有符合当前搜索条件的视频（共{len(self.video_list)}个）\n确定继续吗？",
            QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No
        )
        if confirm != QMessageBox.StandardButton.Yes:
            return
        """根据当前搜索条件批量归档视频"""
        try:
            # 获取当前搜索条件
            keyword = self.search_input.text().strip() or None
            tag_id = self.search_tag_combo.currentData()
            score = float(self.search_score_input.text()) if self.search_score_input.text() else None
            untagged_only = self.untagged_check.isChecked()
            unrated_only = self.unrated_check.isChecked()

            db = SessionLocal()

            # 查询符合条件的视频（预加载标签）
            videos = search_videos_advanced(
                db=db,
                name=keyword,
                tag_id=tag_id,
                score=score,
                untagged_only=untagged_only,
                unrated_only=unrated_only
            )

            if not videos:
                self.statusBar().showMessage("没有找到符合条件的视频", 3000)
                return

            # 创建进度对话框
            progress = QProgressDialog("批量归档中...", "取消", 0, len(videos), self)
            progress.setWindowTitle("归档进度")
            progress.setWindowModality(Qt.WindowModality.WindowModal)

            success_count = 0
            fail_count = 0

            for i, video in enumerate(videos):
                if progress.wasCanceled():
                    break

                progress.setValue(i)
                progress.setLabelText(f"正在处理: {video.name[:20]}...")

                try:
                    if not video.url:
                        fail_count += 1
                        continue

                    src_path = Path(video.url)
                    if not src_path.exists():
                        fail_count += 1
                        continue

                    # 获取标签名称（至少一个标签）
                    tag_names = [tag.name for tag in video.tags]
                    if not tag_names:
                        if not untagged_only:  # 如果不是专门查未标记视频
                            fail_count += 1
                            continue
                        tag_names = ["未标记"]

                    # 构建归档路径（格式：父目录/主标签/评分/文件名）
                    parent_dir = src_path.parent.parent
                    main_tag = tag_names[0]  # 使用第一个标签作为主分类
                    score_str = str(video.score) if video.score is not None else "未评分"

                    dest_dir = parent_dir / main_tag / score_str
                    dest_dir.mkdir(parents=True, exist_ok=True)

                    # 移动文件
                    dest_path = dest_dir / src_path.name
                    shutil.move(str(src_path), str(dest_path))

                    # 更新数据库
                    video.url = str(dest_path)
                    success_count += 1

                except Exception as e:
                    print(f"归档失败 {video.name}: {str(e)}")
                    fail_count += 1

            db.commit()
            progress.close()

            # 刷新界面
            self.load_real_data()

            # 显示结果
            msg = f"归档完成: 成功 {success_count} 个, 失败 {fail_count} 个"
            self.statusBar().showMessage(msg, 5000)

        except Exception as e:
            self.statusBar().showMessage(f"批量归档出错: {str(e)}", 5000)
            print(f"批量归档错误: {e}")
        finally:
            db.close()
    def on_import_videos(self):
        """导入视频文件到数据库"""
        try:
            # 选择文件夹对话框
            directory = QFileDialog.getExistingDirectory(
                self,
                "选择视频文件夹",
                os.path.expanduser("~")  # 默认从用户目录开始
            )

            if not directory:
                return  # 用户取消了选择

            # 支持的视频格式
            video_extensions = (
                '.mp4', '.ts', '.avi', '.mov', '.wmv',
                '.flv', '.mkv', '.webm', '.mpeg',
                '.mpg', '.3gp', '.ogg'
            )

            # 获取数据库会话
            db = SessionLocal()

            try:
                imported_count = 0
                skipped_count = 0

                # 遍历文件夹
                for root, _, files in os.walk(directory):
                    for file in files:
                        if file.lower().endswith(video_extensions):
                            video_path = Path(root) / file

                            # 检查是否已存在
                            existing = db.query(Video).filter(
                                Video.name == file
                            ).first()

                            if existing:
                                skipped_count += 1
                                continue

                            # 添加到数据库
                            db_video = Video(
                                name=file,
                                url=str(video_path)
                            )
                            db.add(db_video)
                            imported_count += 1

                db.commit()

                # 刷新列表
                self.load_real_data()

                # 显示结果
                msg = f"导入完成: 新增 {imported_count} 个, 跳过 {skipped_count} 个已存在视频"
                self.statusBar().showMessage(msg, 5000)

            except Exception as e:
                db.rollback()
                self.statusBar().showMessage(f"导入失败: {str(e)}", 5000)
                print(f"导入错误: {e}")
            finally:
                db.close()

        except Exception as e:
            self.statusBar().showMessage(f"选择文件夹失败: {str(e)}", 5000)
            print(f"文件夹选择错误: {e}")
    def on_slider_pressed(self):
        """当用户按下进度条时暂停播放"""
        if self.player.is_playing():
            self.was_playing = True
            self.player.pause()
        else:
            self.was_playing = False

    def toggle_play_pause(self):
        """切换播放/暂停状态"""
        if self.player.is_playing():
            self.player.pause()
            self.play_btn.setText("播放")
        else:
            self.player.play()
            self.play_btn.setText("暂停")

    def on_slider_released(self):
        """当用户释放进度条时跳转到指定位置"""
        target_pos = self.progress_slider.value() / 1000.0
        self.player.set_position(target_pos)

        if self.was_playing:
            self.player.play()
    def on_video_double_clicked(self, item):
        """处理视频列表双击事件"""
        self.play_selected()  # 直接调用现有的播放方法

    def load_tags(self):
        """加载标签到两个下拉框"""
        tags = get_all_tags()
        self.tag_combo.clear()
        self.search_tag_combo.clear()

        # 添加标签到编辑下拉框
        self.tag_combo.addItem("选择标签", None)
        for tag in sorted(tags, key=lambda x: x.name):
            self.tag_combo.addItem(tag.name, tag.id)

        # 添加标签到搜索下拉框
        self.search_tag_combo.addItem("所有标签", None)
        for tag in sorted(tags, key=lambda x: x.name):
            self.search_tag_combo.addItem(tag.name, tag.id)

    def load_real_data(self):
        """从数据库加载真实数据（修复会话问题）"""
        db = SessionLocal()
        try:
            # 使用 joinedload 预加载 tags
            videos = db.query(Video).options(joinedload(Video.tags)).all()

            self.video_list.clear()
            for video in videos:
                item = QListWidgetItem()
                text = f"{video.name}\n"
                text += f"标签: {', '.join(tag.name for tag in video.tags)}\n" if video.tags else "标签: 无\n"
                text += f"评分: {video.score if video.score is not None else '未评分'}"

                item.setText(text)
                item.setData(Qt.ItemDataRole.UserRole, video.id)
                self.video_list.addItem(item)
        finally:
            db.close()

    # ========== 数据库交互方法 ==========

    def on_save(self):
        """保存标签和评分"""
        selected_item = self.video_list.currentItem()
        if not selected_item:
            self.statusBar().showMessage("请先选择视频", 3000)
            return

        video_id = selected_item.data(Qt.ItemDataRole.UserRole)

        # 保存评分
        score_text = self.score_input.text()
        if score_text:
            try:
                score = int(score_text)
                if 1 <= score <= 10:
                    rate_video(video_id, float(score))
                else:
                    self.statusBar().showMessage("评分必须是1-10的整数", 3000)
                    return
            except ValueError:
                self.statusBar().showMessage("请输入有效的评分(1-10)", 3000)
                return

        # 保存标签
        tag_id = self.tag_combo.currentData()
        if tag_id is not None:  # 确保不是"选择标签"
            add_tag_to_video(video_id, tag_id)

        self.statusBar().showMessage("保存成功", 3000)
        self.load_real_data()  # 刷新列表显示新评分
        self.on_search()

    def on_search(self):
        self.setCursor(Qt.CursorShape.WaitCursor)
        """执行高级搜索（修复会话问题）"""
        try:
            # 获取搜索条件
            keyword = self.search_input.text().strip() or None
            tag_id = self.search_tag_combo.currentData()
            score = float(self.search_score_input.text()) if self.search_score_input.text() else None
            untagged_only = self.untagged_check.isChecked()
            unrated_only = self.unrated_check.isChecked()

            # 获取数据库会话
            db = SessionLocal()

            try:
                # 调用高级搜索
                videos = search_videos_advanced(
                    db=db,
                    name=keyword,
                    tag_id=tag_id,
                    score=score,
                    untagged_only=untagged_only,
                    unrated_only=unrated_only
                )

                # 在会话关闭前处理所有需要的关系数据
                video_data = []
                for video in videos:
                    # 在会话有效时获取标签信息
                    tag_names = [tag.name for tag in video.tags] if video.tags else []
                    video_data.append({
                        'id': video.id,
                        'name': video.name,
                        'tags': tag_names,
                        'score': video.score,
                        'url': video.url
                    })

                # 显示结果
                self.video_list.clear()
                for data in video_data:
                    item = QListWidgetItem()
                    text = f"{data['name']}\n"
                    text += f"标签: {', '.join(data['tags'])}\n" if data['tags'] else "标签: 无\n"
                    text += f"评分: {data['score'] if data['score'] is not None else '未评分'}"
                    item.setText(text)
                    item.setData(Qt.ItemDataRole.UserRole, data['id'])
                    self.video_list.addItem(item)

            finally:
                # 确保会话关闭
                db.close()

        except Exception as e:
            self.statusBar().showMessage(f"搜索失败: {str(e)}", 3000)
            print(f"搜索错误: {e}")

    def on_delete(self):
        """删除选中视频（数据库记录+本地文件）"""
        selected_items = self.video_list.selectedItems()
        if not selected_items:
            self.statusBar().showMessage("请先选择要删除的视频", 3000)
            return

        # 确认对话框（显示更详细的信息）
        video_names = [item.text().split('\n')[0] for item in selected_items]
        confirm_msg = QMessageBox()
        confirm_msg.setIcon(QMessageBox.Icon.Warning)
        confirm_msg.setWindowTitle("确认删除")
        confirm_msg.setText(f"即将永久删除以下 {len(selected_items)} 个视频:")
        confirm_msg.setInformativeText("\n".join(f"• {name[:30]}..." if len(name) > 30 else f"• {name}"
                                                 for name in video_names[:5]))  # 最多显示5个
        if len(video_names) > 5:
            confirm_msg.setDetailedText("\n".join(video_names[5:]))
        confirm_msg.setStandardButtons(QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No)

        if confirm_msg.exec() != QMessageBox.StandardButton.Yes:
            return

        db = SessionLocal()
        success_count = 0
        fail_count = 0
        failed_files = []

        # 进度对话框（针对多选情况）
        progress = None
        if len(selected_items) > 3:
            progress = QProgressDialog("删除中...", "取消", 0, len(selected_items), self)
            progress.setWindowModality(Qt.WindowModality.WindowModal)

        try:
            for i, item in enumerate(selected_items):
                if progress and progress.wasCanceled():
                    break


                video_id = item.data(Qt.ItemDataRole.UserRole)
                video = db.query(Video).filter(Video.id == video_id).first()

                if not video:
                    continue

                try:
                    # 删除本地文件（带安全检查）
                    if video.url:
                        file_path = Path(video.url)
                        if file_path.exists():
                            try:
                                # 尝试先关闭可能打开的文件句柄
                                if sys.platform == "win32":
                                    os.system(f'handle.exe /p {file_path} > NUL 2>&1')
                                file_path.unlink()
                                print(f"已删除文件: {file_path}")
                            except PermissionError as pe:
                                raise Exception(f"文件被占用或无权限: {str(pe)}")
                            except Exception as e:
                                raise Exception(f"文件删除失败: {str(e)}")

                    # 删除数据库记录
                    db.delete(video)
                    db.commit()
                    success_count += 1

                except Exception as e:
                    db.rollback()
                    fail_count += 1
                    failed_files.append(f"{video.name}: {str(e)}")
                    print(f"删除错误 {video.name}: {e}")

            # 刷新列表
            self.load_real_data()

            # 显示结果
            msg = f"删除完成: 成功 {success_count} 个"
            if fail_count > 0:
                msg += f", 失败 {fail_count} 个\n失败原因: {', '.join(failed_files[:3])}"  # 最多显示3个失败原因
                if len(failed_files) > 3:
                    msg += " 等..."

            self.statusBar().showMessage(msg, 7000 if fail_count > 0 else 3000)

        except Exception as e:
            db.rollback()
            self.statusBar().showMessage(f"删除操作出错: {str(e)}", 5000)
        finally:
            if progress:
                progress.close()
            db.close()

    def on_batch_delete(self):
        """根据当前搜索条件批量删除视频"""
        # 获取当前搜索条件
        keyword = self.search_input.text().strip() or None
        tag_id = self.search_tag_combo.currentData()
        score = float(self.search_score_input.text()) if self.search_score_input.text() else None
        untagged_only = self.untagged_check.isChecked()
        unrated_only = self.unrated_check.isChecked()

        db = SessionLocal()
        try:
            # 查询符合条件的视频
            videos = search_videos_advanced(
                db=db,
                name=keyword,
                tag_id=tag_id,
                score=score,
                untagged_only=untagged_only,
                unrated_only=unrated_only
            )

            if not videos:
                self.statusBar().showMessage("没有找到符合条件的视频", 3000)
                return

            # 增强型确认对话框
            confirm = QMessageBox(self)
            confirm.setIcon(QMessageBox.Icon.Warning)
            confirm.setWindowTitle("危险操作确认")
            confirm.setText(f"即将永久删除 {len(videos)} 个符合当前搜索条件的视频！")
            confirm.setInformativeText("此操作将同时删除数据库记录和本地文件，且不可恢复！")

            # 添加显示前5个视频名称
            sample_names = "\n".join([f"• {v.name[:30]}..." if len(v.name) > 30 else f"• {v.name}"
                                      for v in videos[:5]])
            confirm.setDetailedText(f"示例视频:\n{sample_names}")

            # 添加二次确认复选框
            confirm.setCheckBox(QCheckBox("我理解此操作的危险性，确认删除"))
            confirm.setStandardButtons(QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No)

            if confirm.exec() != QMessageBox.StandardButton.Yes or not confirm.checkBox().isChecked():
                return

            # 进度对话框
            progress = QProgressDialog("批量删除中...", "取消", 0, len(videos), self)
            progress.setWindowTitle("删除进度")
            progress.setWindowModality(Qt.WindowModality.WindowModal)

            success_count = 0
            fail_count = 0
            failed_items = []

            for i, video in enumerate(videos):
                if progress.wasCanceled():
                    break

                progress.setValue(i)
                progress.setLabelText(f"正在处理: {video.name[:20]}...")

                try:
                    # 删除本地文件
                    if video.url:
                        file_path = Path(video.url)
                        if file_path.exists():
                            try:
                                # Windows系统尝试解除文件占用
                                if sys.platform == "win32":
                                    try:
                                        import win32api
                                        win32api.SetFileAttributes(str(file_path), win32api.FILE_ATTRIBUTE_NORMAL)
                                    except:
                                        pass
                                file_path.unlink()
                            except Exception as e:
                                raise Exception(f"文件删除失败: {str(e)}")

                    # 删除数据库记录
                    db.delete(video)
                    db.commit()
                    success_count += 1

                except Exception as e:
                    db.rollback()
                    fail_count += 1
                    failed_items.append(f"{video.name}: {str(e)}")
                    print(f"删除失败 {video.name}: {e}")

            progress.close()

            # 刷新数据
            self.load_real_data()

            # 显示详细结果
            result_msg = QMessageBox(self)
            result_msg.setWindowTitle("删除结果")
            result_msg.setText(f"操作完成: 成功 {success_count} 个, 失败 {fail_count} 个")

            if failed_items:
                result_msg.setDetailedText("\n".join(failed_items[:10]))  # 最多显示10个失败项
            result_msg.exec()

        except Exception as e:
            self.statusBar().showMessage(f"批量删除出错: {str(e)}", 5000)
            print(f"批量删除错误: {e}")
        finally:
            db.close()


    # ========== 播放控制方法 ==========
    def play_selected(self):
        """播放选中视频（优化后的版本）"""
        selected_item = self.video_list.currentItem()
        if not selected_item:
            return

        video_id = selected_item.data(Qt.ItemDataRole.UserRole)
        video = get_video_by_id(video_id)  # 从数据库获取完整信息

        if video:
            # 加载当前视频的评分
            if video.score is not None:
                self.score_input.setText(str(int(video.score)))
            else:
                self.score_input.clear()

            if video.url:
                try:
                    # 停止当前播放
                    if self.player.is_playing():
                        self.player.stop()
                        if hasattr(self, 'timer'):
                            self.timer.stop()

                    # 设置新的媒体
                    media = self.instance.media_new(video.url)
                    self.player.set_media(media)
                    self.player.play()

                    # 更新状态栏显示
                    self.statusBar().showMessage(f"正在播放: {video.name}", 3000)

                    # 启动进度更新定时器
                    if not hasattr(self, 'timer'):
                        self.timer = QTimer()
                        self.timer.timeout.connect(self.update_progress)
                    self.timer.start(500)

                except Exception as e:
                    self.statusBar().showMessage(f"播放失败: {str(e)}", 5000)
                    print(f"播放错误: {e}")

    def update_progress(self):
        """更新播放进度"""
        if self.player.is_playing():
            pos = self.player.get_position()
            length = self.player.get_length()

            seconds = int(pos * length / 1000)
            self.time_label.setText(f"{seconds // 60}:{seconds % 60:02d}")

            self.progress_slider.setValue(int(pos * 1000))

    def closeEvent(self, event):
        """关闭时释放资源"""
        if hasattr(self, 'player'):
            self.player.release()
        event.accept()